from storehouse.exceptions import StorehouseUnderINventory
from storehouse.relationCheckers import hasStorehouseUnappliedInventory
from storehouse.models import product, storehouse
from storehouse.models import order_product
from storehouse.models import *
from django.db import IntegrityError
import sys
from storehouse.relationCheckers import destinationCapacityTest,\
    sourceCapacityTest

def sourceCapacityBookOut(order, order_product_instances,change):
    """
    sourceCapacityBookOut(order, order_product_instances,change)
    book products that will be released
    Arguments:
        order - order to book
        order_product_instances - instances of product to book
        change - True when existing bookin should be changed
    Returns:
        list of booked products

    """
    bookedOut = []
    try:
        storehouse_o =order.storehouse_from
    except:
        print "sourceCapacityBookOut",sys.exc_info()[1]
        return bookedOut
    
    if not storehouse_o:
        return bookedOut
    
    if change:
        prev_booked = storehouse_product_book_out.objects.filter(order = order)
        for prev_booked_i in prev_booked:
            prev_booked_i.delete()
    
    for order_product_instance in order_product_instances:
        bookedOut.append(storehouse_product_book_out.objects.create
                         (
                          
                          storehouse = storehouse_o,
                          product = order_product_instance.product,
                          quantity = order_product_instance.quantity,
                          palete_type = order_product_instance.palette_type,
                          order = order                                                                    
                                                                    
                                                                    ))
    return bookedOut

def destinationCapacityBookIn(order, order_product_instances,change):
    """
    destinationCapacityBookIn(order, order_product_instances,change)
    book products that will be stored in storehouse
    Arguments:
        order - order to booke
        order_priduct_instances - instances of products tat will be booked
        change - if existing booking should be changed
    Returns:
        listt of booked products
    """
    bookedIn = []
    try:
        storehouse_o = order.storehouse_to
    except:
        print "destinationCapacityBookIn",sys.exc_info()
        return bookedIn
    if not storehouse_o:
        return bookedIn
    
    if change:
        #TODO when modify throw away old booked products and book them again
        prev_booked = storehouse_product_book_in.objects.filter(order = order)
        for prev_booked_i in prev_booked:
            prev_booked_i.delete()
    for order_product_instance in order_product_instances:
        bookedIn.append(storehouse_product_book_in.objects.create
                         (
                          
                          storehouse = storehouse_o,
                          product = order_product_instance.product,
                          quantity = order_product_instance.quantity,
                          palete_type = order_product_instance.palette_type, 
                          order =order                                                                   
                                                                    
                                                                    ))
    return bookedIn
def OrderCancel(order_in):
    """
    OrderCancel(order_in)
    cancels order and delete connected bookings
    Arguments:
        order_in - order to be canceled
    Returns:
        None

    """
    booked_in_cancels = storehouse_product_book_in.objects.filter(order = order_in)
    for booked_in_cancel in booked_in_cancels:
        booked_in_cancel.delete()
    booked_out_cancels = storehouse_product_book_out.objects.filter(order = order_in)
    for booked_out_cancel in booked_out_cancels:
        booked_out_cancel.delete()
    order_in.state = order_state.objects.get(name  ='Anulowany')
    order_in.save()

def orderArchive(order_in):
    """
    orderArchive(order_in)
    archive order
    Arguments:
        order_in -  order to be archived
    Returns:
        None
    """
    order_in.is_archived = True
    order_in.save()
    
def getOrder_product_instances(order_in):
    """
    getOrder_product_instances(order_in)
    Get products connected to order
    Arguments:
        order_in - order
    Returns:
        lsit of product instances connected to order
    """
    return order_product.objects.filter(order = order_in)

def storeOrder(order_in):
    """
    storeOrder(order_in)
        stores order in storehouse
        create barcodes for new products
        delete booked_in products connected with order
        add new storehouse_product objects

    Arguments:
        order_in - order to be stored
    Returns:
        None
    Throws:
        StorehouseUnderINventory
    """
    order_product_instances = getOrder_product_instances(order_in)
   # destinationCapacityTest(order_in,order_product_instances=order_product_instances,change = True)
    dst_storehouse = order_in.storehouse_to
    if hasStorehouseUnappliedInventory(dst_storehouse):
        raise StorehouseUnderINventory("")
    
    try:
        for order_product_instance in order_product_instances:
            
            for i in range(order_product_instance.quantity):
                if order_product_instance.barcode:
                    
                    addedBarCode = barcode.objects.create(
                                                          barcode_no ="%s/%i" %(order_product_instance.barcode.barcode_no,i),
                                                          path = "%s/%i" %(order_product_instance.barcode.path,i)
                                                          )
                else:
                    addedBarCode = barcode.objects.create(
                                                          barcode_no ="%s/" %(order_product_instance.product.symbol),
                                                          path = "%s/" %(order_product_instance.product.symbol)
                                                          )
                    addedBarCode.barcode_no = "%s%i" % (addedBarCode.barcode_no,addedBarCode.id)
                    addedBarCode.path =  "%s%i" % (addedBarCode.barcode_no,addedBarCode.id)
                    addedBarCode.save()
                
                storehouse_product.objects.create(
                                                  
                                                  product = order_product_instance.product,
                                                  palete_type = order_product_instance.palette_type,
                                                  storehouse = dst_storehouse,
                                                  barcode = addedBarCode
                                                  )
        booked_products = storehouse_product_book_in.objects.filter(order = order_in)
        for booked_product in booked_products:
            booked_product.delete()
        
    except:
        print "storeOrder",sys.exc_info()
        raise
def sendOrder(order_in):
    """
    sendOrder(order_in)
        send order from storehouse
        delete booked_out objects connected with order
        delete storehouse_product connected with order

    Arguments:
        order_in - order to be sent
    Returns:
        None
    Throws:
        StorehouseUnderINventory


    """
    #get product with properly palette type and del random 10(we don't have any algorithm to do that)
    order_product_instances = getOrder_product_instances(order_in)
   # sourceCapacityTest(order_in,order_product_instances=order_product_instances,change=False)
    src_storehouse = order_in.storehouse_from
    if hasStorehouseUnappliedInventory(src_storehouse):
        raise StorehouseUnderINventory("")
    
    for order_product_instance in order_product_instances:
        products_to_del  = storehouse_product.objects.filter(storehouse = src_storehouse,product =order_product_instance.product,\
                                palete_type = order_product_instance.palette_type)[:order_product_instance.quantity]
        
        for product_to_del in products_to_del:
            new_order_product_instance = order_product.objects.create(
                                                                          product =product_to_del.product,
                                                                          order = order_in,
                                                                          barcode = product_to_del.barcode,
                                                                          palette_type = product_to_del.palete_type, 
                                                                          quantity = 1, 
                                                                          expiration_date =order_product_instance.expiration_date,
                                                                          description = order_product_instance.description,
                                                                      )
            product_to_del.delete()
            
        order_product_instance.delete()
    
    
    
            
    
    booked_products = storehouse_product_book_out.objects.filter(order = order_in)
    for booked_product in booked_products:
        booked_product.delete()    

def completeRW(order_in,request):
    """
    completeRW(order_in,request)
    complete generation of RW document
    Arguments:
        order_in -  order connected with document
        request  - unused
    Returns:
        None
    Throws:
        StorehouseUnderINventory
    """
    sendOrder(order_in)
    
def completePW(order_in,request):
    """
    completePW(order_in,request)
    complete generation of PW document
    Arguments:
        order_in -  order connected with document
        request  - request
    Returns:
        None
    Throws:
        StorehouseUnderINventory
    """
    storeOrder(order_in)
    generateMM(order_in,request)
    
def completePZ(order_in,request):
    """
    completePZ(order_in,request)
    complete generation of PZ document
    Arguments:
        order_in -  order connected with document
        request  - request
    Returns:
        None
    Throws:
        StorehouseUnderINventory
    """
    storeOrder(order_in)

    
def completeWZ(order_in,request):
    """
    completeWZ(order_in,request)
    complete generation of WZ document
    Arguments:
        order_in -  order connected with document
        request  - request
    Returns:
        None
    Throws:
        StorehouseUnderINventory
    """
    sendOrder(order_in)
    
def generateMM(order_in,request):
    """
    generateMM(order_in,request)
    complete generation of MM document
    Arguments:
        order_in -  order connected with document
        request  - request
    Returns:
        None
    Throws:
        StorehouseUnderINventory
    """
    document_o = document.objects.create(
                                         document_type = document_type.objects.get(symbol = 'MM'),
                                         creator = user.objects.get(user_ptr = request.user),
                                         storehouse  = order_in.storehouse_to,
                                         order =order_in,
                                         )
    
    document_o.save()

